package com.ruoyi.web.controller.weather;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.http_utils.AsyncHttpMultipleRequestsExample;
import com.ruoyi.web.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

/**
 * 站点天气controller
 *
 * @author xuezhenwei
 * @date 2025-03-06 14:03
 */
@RestController
@RequestMapping("/site/weather")
@Slf4j
public class SiteWeatherController {

    @Autowired
    private HttpUtils httpUtils;

    @Autowired
    private AsyncHttpMultipleRequestsExample asyncHttpMultipleRequestsExample;

    private final String SEARCH_URL = "http://58.59.29.50:11002/Weather/ZDZ";

    private final String SITE_SEARCH_URL = "http://58.59.29.50:11002/Weather/ZDZ";

    private final ObjectMapper objectMapper = new ObjectMapper();


    @PostMapping("/search")
    public AjaxResult search(@RequestBody Map<String,Object> params){

        // 如果不传这些参数不能访问！
        if (!params.containsKey("STATIONCODE") || !params.containsKey("stateTime") || !params.containsKey("endtime")){
            throw new RuntimeException("缺少参数！");
        }

            String format = StringUtils.format("ZDZ.GetDataListByStationCodesAndWeatherKeysAndTimeRanges|1|String;onehour|String;{}|String;rain_sum_curhour,airtemp_current,wind_current,rh_current,visibility_current,rain_sum_tenminute,visibility_oneminute,visibility_min,seapressure_current|DateTime;{}|DateTime;{}",
                    params.get("STATIONCODE"), params.get("stateTime"), params.get("endtime"));
            try {
                params.put("projectname" , "");
                params.put("calltype" , 4);
                params.put("iquery" , format);
                String result = httpUtils.httpUtil(params, SEARCH_URL);
                return AjaxResult.success("请求成功" , result);
            } catch (Exception e) {
                log.error("获取站点天气信息失败！ message: {}" , e.getMessage());
                throw new RuntimeException("获取站点天气信息异常！");
            }
    }

    @GetMapping("/site/search")
    public AjaxResult siteSearch(){

        String format = StringUtils.format("ZDZ.GetRainSumByCollectionCodeAndMinutesAndQueryTime|1|String;tenminute|String;shandong_area|Int32;60|DateTime;{}",
                DateUtil.format(new Date() , "yyyy-MM-dd HH:mm:ss"));

        String result;
        Map<String,Object> params = new LinkedHashMap<>();
        try {
            params.put("projectname" , "");
            params.put("calltype" , 5);
            params.put("iquery" , format);
            result = httpUtils.httpUtil(params, SITE_SEARCH_URL);

        } catch (Exception e) {
            log.error("获取站点信息失败！ message: {}" , e.getMessage());
            throw new RuntimeException("获取站点信息异常！");
        }

        Map<String , Object> value = new HashMap<>();
        try {
            value  = objectMapper.readValue(result, Map.class);
        } catch (JsonProcessingException e) {
            log.error("获取站点信息失败! message: {}" , e.getMessage());
            throw new RuntimeException("获取站点信息异常");
        }
        if (Objects.isNull(value.get("FieldName")) || Objects.isNull(value.get("FieldType")) || Objects.isNull(value.get("Rows"))){
            throw new RuntimeException("获取站点信息异常！");
        }

        return AjaxResult.success("请求成功" , analysis(value));
    }



    private List<Map<String, Object>> analysis(Map<String , Object> objectMap){

        List<Map<String, Object>> result = new LinkedList<>();

        Object fieldName = objectMap.get("FieldName");
        Object rows = objectMap.get("Rows");
        List<String> fieldList = new LinkedList<>();
        if (fieldName instanceof List){
            fieldList = (List<String>) fieldName;
        }
        int cityCodeIndex = fieldList.indexOf("CITYCODE");

        List<List<Object>> rowsData = (List<List<Object>>) rows;

        for (Iterator<List<Object>> iterator = rowsData.stream().iterator(); iterator.hasNext();) {
            List<Object> row = iterator.next();
            if (Objects.equals("371500" , row.get(cityCodeIndex))){
                // 只有等于371500才是聊城的站点,构造返回数据
                Map<String , Object> resultMap = new LinkedHashMap<>();
                for (int i = 0; i < row.size(); i++) {
                    resultMap.put(fieldList.get(i) , row.get(i));
                }
                result.add(resultMap);
            }
        }
        return result;
    }

    @PostMapping("/async/search")
    public AjaxResult AsyncSearch(@RequestBody Map<String,Object> params){

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 如果不传这些参数不能访问！
        if (!params.containsKey("STATIONCODE") || !params.containsKey("stateTime") || !params.containsKey("endtime")){
            throw new RuntimeException("缺少参数！");
        }
        List<String> cityCodeList = (List)params.get("STATIONCODE");
        if(CollectionUtil.isEmpty(cityCodeList)){
            throw new RuntimeException("编码集合不能为空!");
        }

        List<URI> urls = new ArrayList<>();
        for (String cityCode : cityCodeList) {
            String format = StringUtils.format("ZDZ.GetDataListByStationCodesAndWeatherKeysAndTimeRanges|1|String;onehour|String;{}|String;rain_sum_curhour,airtemp_current,wind_current,rh_current,visibility_current,rain_sum_tenminute,visibility_oneminute,visibility_min,seapressure_current|DateTime;{}|DateTime;{}",
                    cityCode, params.get("stateTime"), params.get("endtime"));
            params.put("projectname" , "");
            params.put("calltype" , 4);
            params.put("iquery" , format);
            urls.add(buildUrl(params));
        }

        List<HttpResponse> httpResponses = null;
        try {
            httpResponses = asyncHttpMultipleRequestsExample.asyncSend(urls);
        } catch (IOReactorException e) {
            log.error("执行请求失败 message: {}" , e.getMessage());
            throw new RuntimeException("请求失败！");
        }

        stopWatch.stop();

        log.info("请求耗时 {} s" , stopWatch.getTotalTimeSeconds());

        List<Map<String , Object>> result = new LinkedList<>();
        //处理结果
        for (HttpResponse httpResponse : httpResponses) {
            HttpEntity entity = httpResponse.getEntity();
            String entityStr = "";
            Map<String , Object> objectMap = new LinkedHashMap<>();
            try {
                entityStr = EntityUtils.toString(entity, "UTF-8");
                if (StringUtils.isBlank(entityStr)){
                    continue;
                }
                objectMap = objectMapper.readValue(entityStr , Map.class);
            } catch (IOException e) {
                log.info("获取响应失败! message:{}" , e.getMessage());
            }
            if (CollectionUtil.isEmpty((List)objectMap.get("Rows"))){
                continue;
            }

            Map<String , Object> objMap = (Map<String, Object>) ((List)objectMap.get("Rows")).get(0);
            result.add(objMap);
        }

        return AjaxResult.success("处理成功" , result);
    }


    private URI buildUrl(Map<String,Object> params){
        List<NameValuePair> requestParam = new ArrayList<>();
        if (!CollectionUtils.isEmpty(params)){
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                requestParam.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
            }
        }
        URIBuilder uriBuilder = null;
        URI uri = null;
        try {
            uriBuilder = new URIBuilder(SEARCH_URL);
            uriBuilder.setParameters(requestParam);
            uri = uriBuilder.build();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return uri;
    }

}
